#include "sysTick.h"

const static uint8_t _g_fac_us = SYSTICK / 8000000;         // us延时倍乘数
const static uint16_t _g_fac_ms = SYSTICK / 8000000 * 1000; // ms延时倍乘数

/**
 * @name 微秒延时
 * @description
 * @function
 * @param {uint32_t} nus 延时时间（nus <= 0xffffff * 8 * 1000 / SYSTICK * 1000）
 * @returns {void}
 * @requires [nus]
 */
static void _delay_us(const uint32_t nus) {
    uint32_t ctrl;
    // 加载时间
    SysTick->LOAD = nus * _g_fac_us;
    // 清空计数
    SysTick->VAL = 0x00;
    // 开始倒数
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    // 等待时间
    do
        ctrl = SysTick->CTRL;
    while (ctrl & 0x01 && !(ctrl & (1 << 16)));
    // 关闭计数
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    // 清空计数
    SysTick->VAL = 0X00;
}

/**
 * @name 毫秒延时
 * @description
 * @function
 * @param {uint32_t} nms 延时时间（nms <= 0xffffff * 8 * 1000 / SYSTICK）
 * @returns {void}
 * @requires [nms]
 */
static void _delay_ms(const uint32_t nms) {
    uint32_t ctrl;
    // 加载时间
    SysTick->LOAD = nms * _g_fac_ms;
    // 清空计数
    SysTick->VAL = 0x00;
    // 开始倒数
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    // 等待时间
    do
        ctrl = SysTick->CTRL;
    while (ctrl & 0x01 && !(ctrl & (1 << 16)));
    // 关闭计数
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    // 清空计数
    SysTick->VAL = 0X00;
}

/**
 * @name 滴答计时器初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void sysTick_init(void) {
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}

/**
 * @name 微秒延时
 * @description
 * @function
 * @param {uint32_t} nus 延时时间
 * @returns {void}
 * @requires [nus]
 */
void delay_us(uint32_t nus) {
    const static uint32_t max_delay = 0xffffff * 8 * 1000 / SYSTICK * 1000;
    while (nus >= max_delay) {
        _delay_us(max_delay);
        nus -= max_delay;
    }
    _delay_us(nus);
}

/**
 * @name 毫秒延时
 * @description
 * @function
 * @param {uint32_t} nms 延时时间
 * @returns {void}
 * @requires [nms]
 */
void delay_ms(uint32_t nms) {
    const static uint32_t max_delay = 0xffffff * 8 * 1000 / SYSTICK;
    while (nms >= max_delay) {
        _delay_ms(max_delay);
        nms -= max_delay;
    }
    _delay_ms(nms);
}